'use strict';
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const Controller = require('egg').Controller;
//故名思意 异步二进制 写入流
const awaitWriteStream = require('await-stream-ready').write;
//管道读入一个虫洞。
const sendToWormhole = require('stream-wormhole');
const md5 = require("md5");
const moment = require("moment");
const atob = require('atob');

class UploadController extends Controller {
    decodeID(base64) {
        const decode = atob(base64);
        return decode.split("@")[1];
    }

    async mkdir(filePath) {
        return new Promise((resolve, reject) => {
            fs.mkdir(filePath, (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            })
        })
    }

    dealFilePath(exname) {
        let filePath = ''
        if (/(png|jpg|gif|jpeg|psd)$/.test(exname)) {
            filePath = '/file/avatar/' + exname + "/" + moment().format("YYYY/MM/DD") + "/";
        } else if (/(txt|xlsx|xls|csv|json|js|html|xml|css|doc|docx|pdf|md|vue|ts)$/.test(exname)) {
            filePath = '/file/document/' + exname + "/" + moment().format("YYYY/MM/DD") + "/";
        } else if (/(mp3|mp4|acc|rmvb|avi|webm)$/.test(exname)) {
            filePath = '/file/media/' + exname + "/" + moment().format("YYYY/MM/DD") + "/";
        } else if (/(apk|exe|zip|rar|7z)$/.test(exname)) {
            filePath = '/file/other/' + exname + "/" + moment().format("YYYY/MM/DD") + "/";
        } else {
            filePath = '/file/others/' + exname + "/" + moment().format("YYYY/MM/DD") + "/";
        }
        return filePath;
    }

    async upload() {
        const {
            ctx
        } = this;
        const stream = await ctx.getFileStream();
        //新建一个文件名
        const filename = md5(stream.filename) + path
            .extname(stream.filename)
            .toLocaleLowerCase();
        const exname = filename.replace(/.+\./, "").toLowerCase(); //扩展名

        const filePath = this.dealFilePath(exname);
        const pathInfo = path.resolve(__dirname, "../" + filePath);
        const hasPath = await fse.pathExists(pathInfo);

        if (!hasPath) {
            console.log('目录不存在');
            await fse.ensureDir(pathInfo);
        }

        const res = await this.writeFile(filePath, pathInfo, stream);

        const id = this.decodeID(ctx.header.csrftoken)
        if (res.code == 200) {
            let response = await this.service.upload.updateAvatar(res.url, id)
            if (response) {
                ctx.body = res;
            }
        } else {
            ctx.body = res;
        }
    }

    async writeFile(filePath, pathInfo, stream) {
        const ctx = this.ctx;
        //egg-multipart 已经帮我们处理文件二进制对象

        // const stream = await ctx.getFileStream();
        //新建一个文件名
        const filename = md5(stream.filename) + path
            .extname(stream.filename)
            .toLocaleLowerCase();

        //文件生成绝对路径
        const target = path.join(pathInfo, filename);
        //生成一个文件写入 文件流
        const writeStream = fs.createWriteStream(target);
        try {
            //异步把文件流 写入
            await awaitWriteStream(stream.pipe(writeStream));
            const url = filePath + filename;
            return {
                code: 200,
                message: "文件上传成功",
                imgUrl: ctx.host + url,
                url
            };
        } catch (err) {
            //如果出现错误，关闭管道
            await sendToWormhole(stream);
            return {
                code: 400,
                message: "文件上传失败"
            };
        }
    }
}

module.exports = UploadController;